home *** CD-ROM | disk | FTP | other *** search
- /*
- Catharsis (v1.0p)
- Alpha release (p = in progress).
-
- An Amiga shared library to modify ugly looking fonts by attaching a second, modified
- character-bitmap where some pixels may be added or will be overwritten by the newly created.
-
- Status/Copyright: PUBLIC DOMAIN SOFTWARE
- Author: Joerg van de Loo email: Joergloo@aol.com (<- case sensitive)
-
- By the way:
- This is an experimental attempt written by J.v.d.Loo to try to make the 'times' fonts
- useable since these are the default for WEB-browsers.
-
- I hope this library is useable and programmers modify their programs to support this library -
- so that the users have the benefit of readable fonts.
-
- I would greatly appreciate when someone will improve this library or take over the development
- since I'm a bit lazy.
- */
-
- #include <exec/memory.h>
- #include <exec/libraries.h>
-
- #include <dos/dos.h>
-
- #include <graphics/gfxbase.h>
- #include <graphics/gfx.h>
- #include <graphics/rastport.h>
- #include <graphics/text.h>
-
- #include <intuition/intuitionbase.h>
-
- #include <clib/exec_protos.h>
- #include <clib/intuition_protos.h>
- #include <clib/graphics_protos.h>
-
- #include <pragma/exec_lib.h>
- #include <pragma/intuition_lib.h>
- #include <pragma/graphics_lib.h>
-
- #if !defined(__MAXON__) && !defined(__STORM__)
- #include <proto/exec.h>
- #include <proto/intuition.h>
- #include <proto/graphics.h>
- #else
- #include <pragma/exec_lib.h>
- #include <pragma/intuition_lib.h>
- #include <pragma/graphics_lib.h>
- #endif
-
- #ifdef __GNUC__
- #define ASM
- #define REG(reg,arg) arg __asm(#reg)
- #else
- #if !defined (__MAXON__)
- #define ASM __asm
- #endif
- #define REG(reg,arg) register __##reg arg
- #endif
-
- #ifdef __MAXON__
- extern "C" void GetBaseReg( void);
- #define __saveds
- #define ASM
- #endif
-
- #if defined(__MAXON__) || defined(__STORM__)
- #define __inline
- #define __stdargs
- #endif
-
- extern struct GfxBase *GfxBase;
- extern struct IntuitionBase *IntuitionBase;
-
-
- struct SharedLib
- {
- struct Node sl_LibNode;
- UBYTE sl_Flags; // LIB Flags
- UBYTE sl_Pad0; // Dummy
- UWORD sl_NegSize; // LIB Negative size (function table)
- UWORD sl_PosSize; // LIB Positive size (it's this table)
- UWORD sl_Version; // LIB Version
- UWORD sl_Revision; // LIB Revision
- char *sl_IdString; // LIB Detail string
- ULONG sl_Sum; // LIB Checksum
- UWORD sl_OpenCnt; // LIB Open count
- UWORD sl_PatchCnt; // - Internally used
- BPTR sl_SegList; // LIB Segment pointer
- void *sl_OldFuncPtr;
- struct ExecBase *sl_SysBase; // Pointers to SysBase
- struct GfxBase *sl_GfxBase;
- struct IntuitionBase *sl_IntuitionBase;
- struct TextFont *sl_TextFont[256]; // Remembered TextFont pointers
- struct TextFont *sl_CatharsisFont[256]; // Created TextFont pointers
- }; // Size of table (positive size)
-
-
- /* Type definitions */
-
- struct CharInfo
- {
- unsigned short offset;
- unsigned short size;
- };
-
- struct CharArray
- {
- struct CharInfo CharIndex[256]; // Points to each character's CharInfo (see above)
- };
-
- /* This table is used for decoding */
- struct FontDescription
- {
- struct RastPort rport; // For existing, encoded data of font
- struct BitMap bmap;
- struct RastPort destrp; // For the newly, slightly changed font data
- struct BitMap destbm;
-
- unsigned char *data; // Font data information pointer
- unsigned short bytesperrow; // Complete line with information for all chars
-
- unsigned short lowchar; // e.g. 32
- unsigned short hichar; // e.g. 255
-
- unsigned short charheight; // Height of this char
- unsigned short charoffset; // The offset in pixels to reach the information for this char in "data"
- unsigned short charwidth; // The amount of information stored per line for this char (e.g. 9)
- };
-
- /* -------------------------------------------------------------------------------------------------
-
- This is the basic function to modify a single character which takes a given character (namely
- its bitmap) and creates a second character which pixels do not be necessarily in the original
- character, in addition, it doesn't copies pixels one to one into the second character (-bitmap).
- Only pixels which are not present in the original character will be stored in the newly created,
- with the exception of pixels that have to be eleminated respectively exchanged by a different
- colour to make this character better readable.
-
- The newly created charcater should be rendered into the RastPort with a different colour and
- draw-mode JAM1 (JAM1 = do not erase background)
- */
-
- void ModifyCharacter( struct FontDescription *fd)
- {
- register UWORD c0, c, cc, x, charX, y; // Let the compiler choose amount of reg-vars
-
- x = 0; // No pixel in horizontal direction of this char worked out
-
- while (x + 1 < fd->charwidth) // As long some pixels left to do (at least the square should be readable)
- {
- y = 0; // We're at the top of this character
-
- charX = fd->charoffset + x; // Pixel position (X) within source and destination rastport
-
- while (y < fd->charheight - 1) // As long as the square can be read in
- {
- /* Read a square of 2*2 pixels into 'c' and
- a rectangle of 3*2 pixels into 'cc'
- */
-
- if (y == 0) // Only when at top of char we have to read in square's first row pixels...>
- {
- c = (UWORD) ReadPixel( &fd->rport, charX, y);
- c = (c << 1);
- c |= ReadPixel( &fd->rport, charX + 1, y);
- c = (c << 1);
- }
- else // >... else we can use the existing
- {
- c = ((c & 3) << 1); // Since next row is already in 'c'
- }
-
- if (x + 2 < fd->charwidth) // Can the rectangle be read in?
- {
- if (y == 0) // If we have to read in this pixel...
- {
- cc = c;
- cc |= ReadPixel( &fd->rport, charX + 2, y); // 3rd pixel!
- cc = (cc << 1);
- }
- else
- {
- cc = ((cc & 7) << 1); // Otherwise take the rectangle's 2nd row as 1st
- }
- }
-
- // ------------------------------------
-
- c0 = ReadPixel( &fd->rport, charX, y + 1);
- c |= c0;
- cc |= c0;
- c = (c << 1);
- cc = (cc << 1);
-
- c0 = ReadPixel( &fd->rport, charX + 1, y + 1);
- c |= c0;
-
- if (x + 2 < fd->charwidth) // Can the rectangle be read in?
- {
- cc |= c0;
- cc = (cc << 1);
- cc |= ReadPixel( &fd->rport, charX + 2, y + 1); // 3rd pixel!
- }
- else
- {
- cc = 0;
- }
-
- /* 'c' contains a 2*2 square in binary format, e.g:
- 15 = ## 8 + 4
- ## 2 + 1 = 8 + 4 + 2 + 1
-
- 07 = .# 0 + 4
- ## 2 + 1 = 0 + 4 + 2 + 1
-
- 11 = #. 8 + 0
- ## 4 + 2 = 8 + 0 + 2 + 1
-
- 13 = ## 8 + 4
- .# 0 + 1 = 8 + 4 + 0 + 1
-
- 'cc' contains a rectangle of 3*2
- */
-
- if (y <= fd->charheight / 2) // One pixel more than halve of character's height when scanning from top to down
- {
- if (fd->charheight > 15) // Fonts higher than 15 pixels require rectangles of 4*3 and 3*4, which isn't supported,
- { // where the 4*3's value 230 must be changed to 192 and 3*4's 3288 to 3272 (erasing).
- switch (c) // Font is higher than 15 pixels and we applying pixels within an area from top to middle of char
- {
- case 9:
- WritePixel( &fd->destrp, charX, y + 1);
- break;
-
- case 6:
- WritePixel( &fd->destrp, charX, y);
- break;
-
- case 7:
- WritePixel( &fd->destrp, charX, y);
- break;
-
- case 11:
- WritePixel( &fd->destrp, charX + 1, y);
- break;
-
- case 13:
- WritePixel( &fd->destrp, charX, y + 1);
- break;
-
- case 14:
- WritePixel( &fd->destrp, charX + 1, y + 1);
- break;
- }
- }
- else
- {
- switch (c) // Font is smaller 15 pixels in height, thus apply/exchange pixels
- {
- case 9:
- WritePixel( &fd->destrp, charX, y + 1);
- break;
-
- case 6:
- WritePixel( &fd->destrp, charX, y);
- break;
-
- default:
- switch (cc)
- {
- case 30:
- WritePixel( &fd->destrp, charX + 1, y + 1); // Displace pixels
- break;
-
- case 51:
- WritePixel( &fd->destrp, charX + 1, y + 1); // Displace pixels
- break;
-
- default: // NOTE: Following modifiers can make the font look more ugly!
- switch (c)
- {
- case 7:
- WritePixel( &fd->destrp, charX, y);
- break;
-
- case 13:
- WritePixel( &fd->destrp, charX, y + 1);
- break;
- }
- break;
- } // end switch 'cc'
- break; // break default
-
- } // end switch 'c¹'
- } // end inner ELSE
- }
- else // We are going to modify an area from the middle to the bottom of the char
- {
- if (fd->charheight > 15) // See above
- {
- switch (c)
- {
- case 9:
- WritePixel( &fd->destrp, charX, y + 1);
- break;
-
- case 6:
- WritePixel( &fd->destrp, charX, y);
- break;
-
- case 7:
- WritePixel( &fd->destrp, charX, y);
- break;
-
- case 11:
- WritePixel( &fd->destrp, charX + 1, y);
- break;
-
- case 13:
- WritePixel( &fd->destrp, charX, y + 1);
- break;
-
- case 14:
- WritePixel( &fd->destrp, charX + 1, y + 1);
- break;
- }
- }
- else
- {
- switch (c)
- {
- case 9:
- WritePixel( &fd->destrp, charX, y + 1);
- break;
-
- case 6:
- WritePixel( &fd->destrp, charX, y);
- break;
-
- default:
- switch (cc)
- {
- case 30:
- WritePixel( &fd->destrp, charX + 1, y);
- break;
-
- case 51:
- WritePixel( &fd->destrp, charX + 1, y);
- break;
-
- default:
- switch (c)
- {
- case 7:
- WritePixel( &fd->destrp, charX, y);
- break;
-
- case 13:
- WritePixel( &fd->destrp, charX, y + 1);
- break;
- }
- break;
- } // end switch 'cc'
- break; // break default
-
- } // end switch 'c¹'
- }
- }
-
- y ++; // Continue at next row
- }
-
- x ++; // Continue at next horizontal pixel and row zero
- }
-
- }
-
- void ModifyCharacterA( REG(a0,struct FontDescription *fd))
- {
- ModifyCharacter( fd);
- }
-
- /* ---------------------------------------------------------------------------------- */
-
- struct TextFont *CreateCatharsisFont( struct TextFont *font)
- {
- struct TextFont *ctsfont; // New font to create
- struct CharArray *farray; // Pointer to the characters specific data
- unsigned short textchar; // A simple counter
- struct FontDescription *fd; // Var-table
- unsigned long memattr; // Attribute for bitmap-allocation
-
- // Demand memory for faked TextFont (that one we're going to create)
- ctsfont = (struct TextFont *) AllocMem( sizeof (struct TextFont), MEMF_CLEAR);
- if (ctsfont == NULL)
- return NULL;
-
- // Duplicate font-header
- CopyMem( font, ctsfont, sizeof( struct TextFont));
-
-
- // Demand memory for table of variables
- fd = (struct FontDescription *) AllocMem( sizeof (struct FontDescription), MEMF_CLEAR);
- if (fd == NULL)
- {
- FreeMem( ctsfont, sizeof (struct TextFont));
- return NULL;
- }
-
- fd->data = (unsigned char *) font->tf_CharData; // Encoded pixels (PLANAR)
- fd->bytesperrow = font->tf_Modulo; // Bytes in horizontal direction
- fd->lowchar = font->tf_LoChar; // First encoded char
- fd->hichar = font->tf_HiChar; // Last encoded char
- fd->charheight = font->tf_YSize; // Height of all chars
-
- // Create a bitmap for the font we're going to use as input
- fd->bmap.BytesPerRow = fd->bytesperrow;
- fd->bmap.Rows = fd->charheight;
- fd->bmap.Flags = BMF_STANDARD;
- fd->bmap.Depth = 1;
- fd->bmap.pad = NULL;
- fd->bmap.Planes[0] = fd->data;
-
- // Set up a RastPort for the original font so we easily can use system functions to read its data
- InitRastPort( &fd->rport);
- fd->rport.BitMap = &fd->bmap;
-
- // Init a new rastport for the additional pixels (second font) so we can render...
- InitRastPort( &fd->destrp);
- // ...into this created bitmap
- CopyMem( &fd->bmap, &fd->destbm, sizeof (struct BitMap));
-
-
- // Figure out if the font-render data has to be placed in CHIP-Memory
- memattr = MEMF_CHIP; // Default; use PLANAR-data in CHIP-Memory
- if (IntuitionBase->ActiveScreen) // A screen opened?
- {
- if ( GfxBase->LibNode.lib_Version > 38) // At least OS 3 ?
- {
- if ( !GetBitMapAttr( IntuitionBase->ActiveScreen->RastPort.BitMap, BMA_FLAGS) & BMF_STANDARD )
- memattr = NULL; // Use FAST-Memory for PLANAR-data!
- }
- }
-
-
- // We need one additional bitmap (which becomes TextFont->tf_CharData) to render into
- fd->destbm.Planes[0] = (PLANEPTR) AllocMem( fd->bytesperrow * fd->charheight, memattr|MEMF_CLEAR);
- if (!fd->destbm.Planes[0])
- {
- FreeMem( fd, sizeof (struct FontDescription));
- FreeMem( ctsfont, sizeof (struct TextFont));
- return NULL;
- }
-
- // The TextFont-headers data pointer points to this new created bitmap
- ctsfont->tf_CharData = fd->destbm.Planes[0];
- fd->destrp.BitMap = &fd->destbm;
-
- farray = (struct CharArray *) font->tf_CharLoc; // Pointer to each characters specific data
-
- textchar = 0; // Start at first encoded character in bitmap
-
- while (textchar + fd->lowchar <= fd->hichar)
- {
- fd->charoffset = farray->CharIndex[textchar].offset;
- fd->charwidth = farray->CharIndex[textchar].size;
-
- // Do nothing if this char cannot be modified!
- if ( (short) fd->charwidth > (short) 2)
- ModifyCharacter( fd);
- textchar ++;
- }
-
- // Release it - since we don't need it anymore
- FreeMem( fd, sizeof (struct FontDescription));
-
- ctsfont->tf_Accessors = 1;
-
- return ctsfont;
- }
-
- struct TextFont *CreateCatharsisFontA( REG(a0,struct TextFont *font))
- {
- return CreateCatharsisFont( font);
- }
-
- /* ------------------------------------------------------------------------------------- */
-
- struct TextFont *OpenCatharsisFont( struct TextFont *font, REG(a6, struct SharedLib *base))
- {
- struct TextFont *found;
- ULONG i, emptyPtr;
-
- found = NULL;
- emptyPtr = -1L;
- i = 0;
-
- // Scan through list of remembered TextFonts to find the matching one
- while (i < 256 && !found)
- {
- if ( !base->sl_TextFont[i]) // Empty entry?
- {
- if (emptyPtr == -1L) // No empty pointer remembered?
- emptyPtr = i; // Remember first empty pointer
- i ++; // Next
- }
- else // It's non-empty
- {
- if (font == base->sl_TextFont[i])
- {
- found = base->sl_CatharsisFont[i];
- found->tf_Accessors ++;
- }
- else
- {
- i ++; // Skip to next
- }
- }
- }
-
- // If this font is new, check also if there is a free entry useable
- if (!found && emptyPtr != -1L)
- {
- found = CreateCatharsisFont( font);
- if (found)
- {
- base->sl_TextFont[emptyPtr] = font;
- base->sl_CatharsisFont[emptyPtr] = found;
- }
- }
-
- return found;
- }
-
- struct TextFont *OpenCatharsisFontA( REG(a0, struct TextFont *font), REG(a6, struct SharedLib *base))
- {
- return OpenCatharsisFont( font, base);
- }
-
- /* ---------------------------------------------------------------------------------- */
-
- void CloseCatharsisFont( struct TextFont *font, REG(a6, struct SharedLib *base))
- {
- ULONG i, found;
-
- font->tf_Accessors --;
-
- found = -1L;
-
- // Can we remove it?
- if ( (short) font->tf_Accessors < (short) 1)
- {
- i = 0;
- while (i < 256 && found == -1L)
- {
- if (font == base->sl_CatharsisFont[i])
- found = i;
- i ++;
- }
-
- if (found != -1L)
- {
- FreeMem( font->tf_CharData, font->tf_Modulo * font->tf_YSize);
- FreeMem( font, sizeof (struct TextFont));
- base->sl_TextFont[found] = NULL;
- base->sl_CatharsisFont[found] = NULL;
- }
- }
- }
-
- void CloseCatharsisFontA( REG(a0, struct TextFont *font), REG(a6, struct SharedLib *base))
- {
- CloseCatharsisFont( font, base);
- }
-
- /* -------------------------------------------------------------------------------------------------
- Compute for a colour value its corresponding catharsis value.
- Example:
- red bg colour = 27, green bg colour = 56, blue bg colour = 31
- red fg colour = 00, green fg colour = 37, blue fg colour = 08
- normal = set it to TRUE if background is lighter than foreground, otherwise set it to FALSE
- r = ComputeValue( 27, 00, 1);
- g = ComputeValue( 56, 37, 1);
- b = ComputeValue( 31, 08, 1);
-
- */
-
- int ComputeCatharsisValue( int bg, int fg, int percent, int normal)
- {
- int dist, retval;
-
- if (bg > fg)
- dist = bg - fg;
- else
- dist = fg - bg;
-
- // If distance is greater than halve of maximum luminance, darken or lighten pen-luminance
- if (percent >= 50)
- {
- if (normal) // Background is lighter than foreground
- {
- if (bg - 23 >= 0)
- retval = bg - 23; // Darken background by 'n' (here: 3 * bitspergun - 1)
- else
- retval = 0; // Minimum possible
- }
- else // Foreground lighter than background
- {
- if (fg > bg)
- retval = fg - (dist / 2);
- else
- retval = fg;
- }
- }
- else // Interpol. of values
- {
- if (normal)
- {
- retval = (fg * (percent / 2)) / 100;
- }
- else
- {
- retval = (bg * (percent / 2)) / 100;
- }
- }
-
- if (retval < 0)
- retval = 0;
- if (retval > 255)
- retval = 255;
-
- return retval;
- }
-
- int ComputeCatharsisValueA( REG(d0, int bg), REG(d1, int fg), REG(d2, int percent), REG(d3, int normal))
- {
- return ComputeCatharsisValue( bg, fg, percent, normal);
- }
-
- /* ---------------------------------------------------------------------------------- */
-
- ULONG CompressColorValue( ULONG r, ULONG g, ULONG b)
- {
- ULONG val;
-
- val = (r & 0xFF000000L) >> 8;
- val |= (g & 0xFF000000L) >> 16;
- val |= (b & 0xFF000000L) >> 24;
-
- return val;
- }
-
- ULONG CompressColorValueA( REG(d0, ULONG r), REG(d1, ULONG g), REG(d2, ULONG b))
- {
- return CompressColorValue( r, g, b);
- }
-
- /* -------------------------------------------------------------------------------------------------
- Convert a 8-bit colour value into a AmigaOS compatible 32bit one: e.g. v = 139 (0x8B) - 8bit
- result: v = 0x8BBBBBBB - 32bit
- */
-
- ULONG CompatibleColorValue( ULONG v)
- {
- ULONG help, nibble;
-
- nibble = help = (v & 0xF); // 4bit
- nibble = help = (help << 4) | nibble; // 8 bit (byte)
- help = (help << 8) | nibble; // 16 bit (word)
- help = (help << 8) | nibble; // 24 bit
-
- v = (v << 24);
- v |= help; // longword
- return v;
- }
-
- ULONG CompatibleColorValueA( REG(d0, ULONG v))
- {
- return CompatibleColorValue( v);
- }
-
- /* -------------------------------------------------------------------------------------------------
- Compute a new colour-value basing on two that you passed in to this function.
-
- val1: background colour value, 32bit, where the leftmost 8 bits will be ignore by this
- function since it is normally used as alpha channel:
-
- aaRRGGBB: aa - 8 bit alpha, RR - 8 bit red component, GG - 8 bit green component and
- BB - 8 bit blue component
-
- val2: same as val1 but for foreground colour
- red: pointer to a long-word variable to store a AmigaOS 32bit red component value, i.e. 8bit
- (RR) 0x8B would be expanded to 0x8BBBBBBB ready to use by OS 3 graphic functions
- LoadRGB32(), FindColor() and so on.
- 'red' may be zero, then the red-value is not stored
- green: same as for red, but for the green component
- blue: same as for red, but for the blue component
-
- RESULTS:
- Returns a compressed 32bit value, format aaRRGGBB in d0
- If red, green, blue are non-zero, into the supplied variables the OS compatible colour
- values will be dropped
-
- */
-
- ULONG CatharsisColorValue( ULONG val1, ULONG val2, ULONG *red, ULONG *green, ULONG *blue)
- {
- ULONG val3, val4, bg[3], fg[3], r, g, b;
-
- bg[0] = ((val1 & 0xFF0000L) >> 16); // Get red
- bg[1] = ((val1 & 0xFF00L) >> 8); // Get green
- bg[2] = (val1 & 0xFFL); // Get blue
-
- fg[0] = ((val2 & 0xFF0000L) >> 16); // Get red
- fg[1] = ((val2 & 0xFF00L) >> 8); // Get green
- fg[2] = (val2 & 0xFFL); // Get blue
-
-
- /* Figure out if which is lighter (background or foreground) */
- val1 = ((bg[0] * 30) + (bg[1] * 59) + (bg[2] * 11)) / 100;
- val2 = ((fg[0] * 30) + (fg[1] * 59) + (fg[2] * 11)) / 100;
-
- if (val1 > val2)
- {
- val3 = TRUE; // Normal display, background lighter than foreground
- val4 = val1 - val2; // How much in per cent is the background lighter
- }
- else
- {
- val3 = FALSE;
- val4 = val2 - val1; // How much in per cent is the foreground lighter
- }
-
- r = ComputeCatharsisValue( bg[0], fg[0], val4, val3);
- g = ComputeCatharsisValue( bg[1], fg[1], val4, val3);
- b = ComputeCatharsisValue( bg[2], fg[2], val4, val3);
-
- val3 = r;
- val3 = (val3 << 8);
- val3 |= g;
- val3 = (val3 << 8);
- val3 |= b;
-
- r = CompatibleColorValue( r);
- g = CompatibleColorValue( g);
- b = CompatibleColorValue( b);
-
- if (red)
- *red = r;
- if (green)
- *green = g;
- if (blue)
- *blue = b;
-
- return val3;
- }
-
- ULONG CatharsisColorValueA( REG(d0, ULONG val1), REG(d1, ULONG val2), REG(a0, ULONG *red), REG(a1, ULONG *green), REG(a2, ULONG *blue))
- {
- return CatharsisColorValue( val1, val2, red, green, blue);
- }
-
- /* ------------------------------------------------------------------------------------------ */
-
- void CatharsisText( struct RastPort *rp, unsigned char *str, unsigned int len, unsigned int pen, struct TextFont *ctsfont)
- {
- unsigned short x, y, p;
- struct TextFont *f;
-
- x = rp->cp_x;
- y = rp->cp_y;
- p = rp->FgPen;
- f = rp->Font;
-
- Text( rp, str, len);
-
- if (ctsfont)
- {
- SetDrMd( rp, JAM1);
- SetFont( rp, ctsfont);
- Move( rp, x, y);
- SetAPen( rp, pen);
- Text( rp, str, len);
- SetFont( rp, f);
- SetAPen( rp, p);
- }
- }
-
- void CatharsisTextA( REG(a1,struct RastPort *rp), REG(a0,unsigned char *str), REG(d0,unsigned int len), REG(d1,unsigned int pen), REG(a2, struct TextFont *font))
- {
- CatharsisText( rp, str, len, pen, font);
- }
-
- /* ---------------------------------------------------------------------------------- */
-